﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 序列化辅助操作类
    /// </summary>
    public static class SerializeHelper
    {
        #region 静态方法 - 二进制序列化
        /// <summary>
        /// 将对象序列化为byte[]，此方法不需要源类型标记可<see cref="SerializableAttribute"/>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ToBytes(object value)
        {
            byte[] bytes = new byte[Marshal.SizeOf(value)];
            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            Marshal.StructureToPtr(value, ptr, true);
            return bytes;
        }

        /// <summary>
        /// 将byte[]反序列化为对象，此方法不需要源类型标记可<see cref="SerializableAttribute"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static T FromBytes<T>(byte[] bytes)
        {
            Type type = typeof(T);
            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            object obj = Marshal.PtrToStructure(ptr, type);
            return (T)obj;
        }

        #endregion

        #region 静态方法 - XML序列化
        /// <summary>
        /// 将数据序列化为XML形式
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ToXml(object data)
        {
            data.CheckNotNull(nameof(data));
            using MemoryStream ms = new();
            XmlSerializer serializer = new(data.GetType());
            serializer.Serialize(ms, data);
            ms.Seek(0, 0);
            return Encoding.Default.GetString(ms.ToArray());
        }

        /// <summary>
        /// 将XML数据反序列化为强类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T FromXml<T>(string xml)
        {
            xml.CheckNotNull(nameof(xml));
            byte[] bytes = Encoding.Default.GetBytes(xml);
            using MemoryStream ms = new(bytes);
            XmlSerializer serializer = new(typeof(T));
            return (T)serializer.Deserialize(ms);
        }

        /// <summary>
        /// 将数据序列化为XML并写入文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="data"></param>
        public static void ToXmlFile(string fileName, object data)
        {
            fileName.CheckNotNull(nameof(fileName));
            data.CheckNotNull(nameof(data));
            using FileStream fs = new(fileName, FileMode.Create);
            XmlSerializer serializer = new(data.GetType());
            serializer.Serialize(fs, data);
        }

        /// <summary>
        /// 将指定XML数据文件还原为强类型数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static T FromXmlFile<T>(string fileName)
        {
            fileName.CheckFileExists(nameof(fileName));
            using FileStream fs = new(fileName, FileMode.Open);
            XmlSerializer serializer = new(typeof(T));
            return (T)serializer.Deserialize(fs);
        }
        
        #endregion
    }
}
